﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using SCMS.CoreBusinessLogic.Web;
using SCMS.CoreBusinessLogic.ActionFilters;
using SCMS.CoreBusinessLogic.Security;
using SCMS.CoreBusinessLogic.SalaryPayment;
using SCMS.CoreBusinessLogic.OrderRequest;
using SCMS.CoreBusinessLogic.WB;
using SCMS.UI.GeneralHelper;
using SCMS.Model;
using SCMS.UI.Models;
using System.Text;
using System.Data.Objects.DataClasses;
using SCMS.CoreBusinessLogic.NotificationsManager;
using SCMS.Resource;
using SCMS.Utils;

namespace SCMS.UI.Controllers
{
    [MyException]
    public class SalaryPamentController : PortalBaseController
    {
        private ISalaryPaymentService SalaryPService;
        private IOrderRequest oRService;
        private IWayBillService WBService;
        private INotificationService notificationService;

        public SalaryPamentController(IPermissionService permissionService, IUserContext userContext, ISalaryPaymentService SalaryPService, IOrderRequest oRService,
            IWayBillService WBService, INotificationService notificationService)
            : base(userContext, permissionService)
        {
            this.SalaryPService = SalaryPService;
            this.oRService = oRService;
            this.WBService = WBService;
            this.notificationService = notificationService;
        }
        //
        // GET: /SalaryPament/

        public ActionResult Index()
        {
            return View();
        }

        public ActionResult LoadSalaryPayment()
        {
            Models.SalaryPayment model = new Models.SalaryPayment();
            model.EntitySalaryP = new Model.SalaryRequest { TotalPayroll = 0 };
            model.Currencies = new SelectList(oRService.GetCurrencies(countryProg.Id), "Id", "ShortName");
            model.Months = new SelectList(MonthUtility.MonthList, "IntValue", "Text");
            model.Offices = new SelectList(WBService.GetSubOffices(countryProg.Id), "Id", "Name");
            model.EntitySalaryP.RefNumber = string.Format("--{0}--", Resources.Global_String_NewSPM);
            model.EntitySalaryP.PayrollYear = DateTime.Today.Year;
            return View("LoadSalaryPayment", model);
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult SaveSalaryPayment(Models.SalaryPayment entity)
        {
            entity.EntitySalaryP.CountryProgrammeId = countryProg.Id;
            entity.EntitySalaryP.PreparedBy = currentStaff.Id;
            entity.EntitySalaryP.PayrollMonth = MonthUtility.MonthList[entity.EntitySalaryP.Month.Value - 1].Text;
            entity.EntitySalaryP.IsReviewed = false;
            entity.EntitySalaryP.IsAuthorized = false;
            entity.EntitySalaryP.PreparedOn = DateTime.Now;
            SalaryPService.SaveSalaryRequest(entity.EntitySalaryP);
            return SPMItemList(entity.EntitySalaryP.Id);
        }

        private ActionResult PopulateCreateItem(string id, string CurrencyId, string errormessage = "")
        {
            List<ProjectDonor> pdList = oRService.GetProjectNos(countryProg.Id);
            List<BudgetLineView> blList = pdList.Count > 0 ? oRService.GetProjectBugdetLines(pdList[0].Id) : null;
            if (blList == null)
                blList = new List<BudgetLineView>();
            SalaryPaymentItems model = new SalaryPaymentItems()
            {
                EntitySalaryPBL = new SalaryBudgetline { SalaryId = new Guid(id) },
                ProjectNos = new SelectList(pdList, "Id", "ProjectNumber"),
                BudgetLines = new SelectList(blList, "Id", "Description"),
                Items = new SelectList(SalaryPService.GetPayrollItems(countryProg.Id), "Id", "Name")
            };
            ViewBag.CurrencyId = CurrencyId;
            ViewBag.SPID = id;
            return View("LoadSalaryPItem", model);
        }

        public ActionResult LoadSalaryPItem(string id)
        {
            return PopulateCreateItem(id.Split('~').First(), id.Split('~').Last());
        }

        public ActionResult EditSalaryBL(Guid id)
        {
            SalaryBudgetline sbl = SalaryPService.GetSalaryBudgetLineById(id);
            List<ProjectDonor> pdList = oRService.GetProjectNos(countryProg.Id);
            List<BudgetLineView> blList = pdList.Count > 0 ? oRService.GetProjectBugdetLines(sbl.ProjectBudget.BudgetCategory.ProjectDonor.Id) : null;
            if (blList == null)
                blList = new List<BudgetLineView>();
            sbl.Amount = Math.Round(sbl.Amount, 2);
            SalaryPaymentItems model = new SalaryPaymentItems()
            {
                EntitySalaryPBL = sbl,
                ProjectNos = new SelectList(pdList, "Id", "ProjectNumber", sbl.ProjectBudget.BudgetCategory.ProjectDonor.Id),
                BudgetLines = new SelectList(blList, "Id", "Description"),
                Items = new SelectList(SalaryPService.GetPayrollItems(countryProg.Id), "Id", "Name"),
                ProjectDonorId = sbl.ProjectBudget.BudgetCategory.ProjectDonor.Id
            };
            ViewBag.CurrencyId = sbl.SalaryRequest.SalaryCurrencyId;
            ViewBag.SPID = sbl.SalaryId;
            return View("LoadSalaryPItem", model);
        }

        public ActionResult EditSPM(Guid id)
        {
            Models.SalaryPayment model = new Models.SalaryPayment();
            model.EntitySalaryP = SalaryPService.GetSalaryRequestById(id);
            model.Currencies = new SelectList(oRService.GetCurrencies(countryProg.Id), "Id", "ShortName");
            model.Months = new SelectList(MonthUtility.MonthList, "IntValue", "Text", model.EntitySalaryP.Month);
            model.Offices = new SelectList(WBService.GetSubOffices(countryProg.Id), "Id", "Name");
            model.EntitySalaryP.RefNumber = model.EntitySalaryP.RefNumber;
            model.EntitySalaryP.PayrollYear = model.EntitySalaryP.PayrollYear;
            return View("LoadSalaryPayment", model);
        }

        public ActionResult DeleteBL(Guid blId, Guid spmId)
        {
            SalaryPService.DeleteSPMBudgetLineById(blId);
            return SPMItemList(spmId);
        }

        public ActionResult DeleteSPM(Guid id)
        {
            SalaryPService.DeleteSPMById(id);
            return ViewSalaryPayment();
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult SaveSPItem(Models.SalaryPaymentItems entity)
        {
            SalaryRequest spm = SalaryPService.GetSalaryRequestById(entity.EntitySalaryPBL.SalaryId);
            if (entity.EntitySalaryPBL.Id != Guid.Empty)
            {
                var existingBL = SalaryPService.GetSalaryBudgetLineById(entity.EntitySalaryPBL.Id);
                spm.TotalPayroll -= existingBL.Amount;
            }
            spm.TotalPayroll += entity.EntitySalaryPBL.Amount;
            SalaryPService.SaveSalaryBudgetLine(entity.EntitySalaryPBL);
            SalaryPService.SaveSalaryRequest(spm);
            return SPMItemList(entity.EntitySalaryPBL.SalaryId);
        }

        public ActionResult SPMItemList(Guid id, List<BudgetCheckResult> bcrList = null)
        {
            SalaryRequest spm = SalaryPService.GetSalaryRequestById(id);
            List<SalaryBudgetline> TBList = SalaryPService.GetSPBLines(id);
            SalaryPayment model = new SalaryPayment { EntitySalaryP = spm, SalaryPaymentItems = new List<SalaryPaymentItems>(), BudgetCheckResults = bcrList };
            foreach (SalaryBudgetline bc in TBList)
            {
                model.SalaryPaymentItems.Add(new SalaryPaymentItems { EntitySalaryPBL = bc });
            }
            
            return View("SalarPItemsList", model);
        }

        public ActionResult SubmitSPM(Guid id)
        {
            List<BudgetCheckResult> bcrList = SalaryPService.RunFundsAvailableCheck(id);
            if (bcrList.Count > 0)
                return SPMItemList(id, bcrList: bcrList);//Render ECF with message saying funds not sufficient

            SalaryRequest spm = SalaryPService.GetSalaryRequestById(id);
            spm.PreparedBy = currentStaff.Id;
            spm.PreparedOn = DateTime.Now;
            spm.IsReviewed = false;
            spm.IsAuthorized = false;
            spm.IsSubmitted = true;
            spm.RefNumber = SalaryPService.GenerateUniquNumber(countryProg);
            SalaryPService.SaveSalaryRequest(spm);
            //Send Notification
            notificationService.SendToAppropriateApprover(NotificationHelper.spmCode, NotificationHelper.reviewCode, spm.Id);
            return ViewSalaryPayment();
        }

        public ActionResult ViewSalaryPayment()
        {
            List<ViewSalaryPayment> modelList = new List<ViewSalaryPayment>();
            List<SalaryRequest> spmlist = SalaryPService.GetSalaryPayments(countryProg.Id);
            foreach (SalaryRequest spm in spmlist)
            {

                var model = new ViewSalaryPayment()
                {
                    EntitySalaryP = spm
                };
                modelList.Add(model);
            }
            return View("ViewSalaryPayment", modelList);
        }

        public ActionResult GetBudgetLines(Guid id)
        {
            StringBuilder blineOption = new StringBuilder();
            blineOption.Append("<select class=\"dpl\" id=\"BudgetLineID\" name=\"EntitySalaryPBL.BudgetLineId\" onchange = \"javascript:checkBalance()\"><option value=\"\">" + Resources.Global_String_PleaseSelect + "</option>");
            List<Model.BudgetLineView> BLines = oRService.GetProjectBugdetLines(id);
            foreach (BudgetLineView item in BLines)
                blineOption.Append("<option value=\"" + item.Id + "\">" + item.Description + "</option>");
            blineOption.Append("</select>");
            blineOption.Append("<span class=\"field-validation-valid\" data-valmsg-for=\"EntitySalaryPBL.BudgetLineId\" data-valmsg-replace=\"true\"></span>");
            ViewBag.Html = blineOption.ToString();
            return View("HTMLResponse");
        }

        public ActionResult ViewSalaryPaymentDetails(Guid id, bool checkPost = false)
        {
            Models.ViewSalaryPayment model = SalaryPaymentExtension.PrepareSP(id);
            //Manage approval link
            string actionType = null;
            if (model.EntitySalaryP.IsReviewed && !model.EntitySalaryP.IsAuthorized)
                actionType = NotificationHelper.authorizationCode;
            else if (model.EntitySalaryP.IsSubmitted && !model.EntitySalaryP.IsReviewed)
                actionType = NotificationHelper.reviewCode;
            if (actionType != null)
                model.CanApprove = notificationService.CanApprove(currentUser, NotificationHelper.spmCode, actionType, model.EntitySalaryP.Id);
            else
                model.CanApprove = false;
            //Manage Can Edit
            model.CanEdit = (!model.EntitySalaryP.IsSubmitted && !model.EntitySalaryP.IsRejected && model.EntitySalaryP.PreparedBy == currentStaff.Id) ||
                    (model.EntitySalaryP.IsSubmitted && model.EntitySalaryP.IsRejected && !model.EntitySalaryP.IsReviewed && model.EntitySalaryP.PreparedBy == currentStaff.Id);
            //Manage Post Funds Button
            if (userContext.HasPermission(StandardPermissionProvider.SalaryPaymentPostFunds) && checkPost)
                foreach (var spm in SalaryPService.GetSalaryPaymentsForPosting(countryProg.Id, currentUser))
                {
                    if (spm.Id.Equals(model.EntitySalaryP.Id))
                    {
                        model.CanPostFunds = true;
                        break;
                    }
                }

            return View("ViewSalaryPaymentDetails", model);
        }
    }
}